/*
 * @文件描述: 电机控制面板的UI界面 ,motor dashboard
 * @版本: 
 * @作者: 周晨阳
 * 此类只处理简单的UI逻辑,不要在其中加入复杂的逻辑函数,否则容易造成UI卡住
 * view类只处理UI显示，交互等操作，不应让view类处理程序逻辑，有关逻辑的代码应该
 * 在各个逻辑代码中去实现，然后通过调用view中的public方法来改变UI
 * 注意，其中的onView开头的函数都是纯UI函数，调用后只会改变UI显示，不会改变其他逻辑
 * 考虑到现阶段代码不能一下子变得过于复杂，没有加入presenter层，只保留了model和view
 * @Date: 2021-09-23 07:50:59
 */
using System;
using System.Threading;
using System.Windows.Forms;
using System.Text;

namespace Motor_Control
{
    /// <summary>
    /// view类,该类用于管理一切和UI有关的事务
    /// </summary>
    public partial class MotorControlView : Form
    {
        delegate void CloseApp();
        private MotorControl motorControl;
        private SynchronizationContext synchronizationContext;
        private Sensors sensors = Sensors.CreateInstance();

        public MotorControlView(MotorControl motorControl)
        {
            this.motorControl = motorControl;
            InitializeComponent();
        }
        public MotorControlView()
        {
            synchronizationContext = SynchronizationContext.Current;

            InitializeComponent();


        }
        /// <summary>
        /// 绑定电机控制对象和socket对象
        /// </summary>
        /// <param name="model"></param>
        public void bandModel(MotorControl model)
        {
            this.motorControl = model;

        }
        /// <summary>
        /// 设置电机连接状态,同时会自动设置连接按键
        /// </summary>
        /// <param name="c"></param>
        public void onViewSetMotorConnection(MOTOR_CONNECTION c)
        {
            synchronizationContext.Post(_ =>
            {
                switch (c)
                {
                    case MOTOR_CONNECTION.DISCONNECT:
                        this.MotorConnection.Text = "未连接";
                        this.connectMotor.Text = "连接电机";
                        this.connectMotor.Enabled = true;

                        break;
                    case MOTOR_CONNECTION.OK:
                        this.MotorConnection.Text = "已连接";
                        this.connectMotor.Text = "断开电机";
                        this.connectMotor.Enabled = true;


                        break;
                    case MOTOR_CONNECTION.CONNECTING:
                        this.MotorConnection.Text = "正在连接";
                        this.connectMotor.Enabled = false;


                        break;

                }
            }, null);

        }
        /// <summary>
        /// 设置socket连接状态
        /// </summary>
        /// <param name="s"></param>
        public void onViewSetUnityConnection(MY_SOCKET_CONNECT_STATE s)
        {
            synchronizationContext.Post(_ =>
            {
                switch (s)
                {
                    case MY_SOCKET_CONNECT_STATE.CONNECTING:
                        this.socketConnection.Text = "正在连接";
                        break;
                    case MY_SOCKET_CONNECT_STATE.CONNECTED:
                        this.socketConnection.Text = "已连接";
                        break;

                    case MY_SOCKET_CONNECT_STATE.DISCONNECT:
                        this.socketConnection.Text = "未连接";
                        break;

                    case MY_SOCKET_CONNECT_STATE.INITIALIZING:
                        this.socketConnection.Text = "正在初始化";

                        break;
                    case MY_SOCKET_CONNECT_STATE.CONNECTION_FAILED:
                        this.socketConnection.Text = "连接失败";

                        break;


                }

            }, null);

        }
        /// <summary>
        /// 设置COM口显示
        /// </summary>
        /// <param name="com"></param>
        public void onViewAddCOMport(string com)
        {
            synchronizationContext.Post(_ =>
               {
                   this.COMportComboBox.Items.Add(com);
               }, null);

        }
        /// <summary>
        /// 设置需要显示的COM口列表
        /// </summary>
        /// <param name="com">com口列表string</param>
        public void onViewSetCOMPorts(string[] com)
        {
            synchronizationContext.Post(_ =>
            {
                this.COMportComboBox.Items.Clear();
                this.COMportComboBox.Items.AddRange(com);
            }, null);

        }
        /// <summary>
        /// 显示一些debug输出信息到窗口中
        /// </summary>
        /// <param name="s">string</param>
        public void onViewShowDebugInfo(string s)
        {
            synchronizationContext.Post(_ =>
            {

                this.sendStringTextbox.Text = s;
            }, null);
        }
        /// <summary>
        /// 设置不同的角度
        /// </summary>
        /// <param name="sensor"></param>
        /// <param name="value"></param>
        public void onViewSetAngle(SENSOR_ID sensor, double value)
        {
            synchronizationContext.Post(_ =>
            {
                switch (sensor)
                {
                    case SENSOR_ID.SENSOR_1: this.A1_angle.Text = value.ToString(); break;
                    case SENSOR_ID.SENSOR_2: this.A2_angle.Text = value.ToString(); break;
                    case SENSOR_ID.SENSOR_3: this.A3_angle.Text = value.ToString(); break;
                    case SENSOR_ID.SENSOR_4: this.A4_angle.Text = value.ToString(); break;
                    case SENSOR_ID.SENSOR_5: this.A5_angle.Text = value.ToString(); break;
                    case SENSOR_ID.SENSOR_6: this.A6_angle.Text = value.ToString(); break;
                    case SENSOR_ID.SENSOR_7: this.hand_angle.Text = value.ToString(); break;

                }

            }, null);

        }
        /// <summary>
        /// 设置电机显示位置
        /// </summary>
        /// <param name="id"></param>
        /// <param name="pos"></param>
        public void onViewSetMotorPos(MOTOR_ID id, double pos)
        {
            synchronizationContext.Post(_ =>
               {

                   switch (id)
                   {
                       case MOTOR_ID.MOTOR_ID_1:
                           this.motor1Pos.Text = pos.ToString();
                           break;
                       case MOTOR_ID.MOTOR_ID_2:
                           this.motor2Pos.Text = pos.ToString();
                           break;

                   }
               }, null);

        }
        /// <summary>
        /// 设置电机显示加速度
        /// </summary>
        /// <param name="id"></param>
        /// <param name="Acc"></param>
        public void onViewSetMotorAcc(MOTOR_ID id, double Acc)
        {
            synchronizationContext.Post(_ =>
               {

               }, null);

        }
        /// <summary>
        /// 设置电机显示速度
        /// </summary>
        /// <param name="id"></param>
        /// <param name="pos"></param>
        public void onViewSetMotorVel(MOTOR_ID id, double pos)
        {
            synchronizationContext.Post(_ =>
               {

               }, null);

        }
        /// <summary>
        /// 设置电机显示电流
        /// </summary>
        /// <param name="id"></param>
        /// <param name="pos"></param>
        public void onViewSetMotorCur(MOTOR_ID id, double pos)
        {
            synchronizationContext.Post(_ =>
               {

               }, null);

        }
        /// <summary>
        /// 设置串口连接状态
        /// </summary>
        /// <param name="state"></param>
        public void onViewSetSerialState(SENSOR_CONNECTION state)
        {
            synchronizationContext.Post(_ =>
                {

                    switch (state)
                    {
                        case SENSOR_CONNECTION.OK:
                            this.sensorConnection.Text = "已连接";
                            this.connectSensor.Enabled = true;
                            this.connectSensor.Text = "断开连接";

                            ; break;
                        case SENSOR_CONNECTION.CONNECTING:
                            this.sensorConnection.Text = "正在连接";
                            this.connectSensor.Enabled = false;
                            ; break;
                        case SENSOR_CONNECTION.DISCONNECT:
                            this.sensorConnection.Text = "未连接";
                            this.connectSensor.Enabled = true;
                            this.connectSensor.Text = "连接传感器";


                            ; break;

                    }
                }, null);

        }
        /// <summary>
        /// 显示R值
        /// </summary>
        /// <param name="id"></param>
        /// <param name="r"></param>
        public void onViewSetSensorR(SENSOR_ID id, double r)
        {
            synchronizationContext.Post(_ =>
            {

                switch (id)
                {
                    case SENSOR_ID.SENSOR_1:
                        A1_R.Text = r.ToString();
                        break;
                    case SENSOR_ID.SENSOR_2:
                        A2_R.Text = r.ToString();
                        break;

                    case SENSOR_ID.SENSOR_3:
                        A3_R.Text = r.ToString();
                        break;

                    case SENSOR_ID.SENSOR_4:
                        A4_R.Text = r.ToString();
                        break;

                    case SENSOR_ID.SENSOR_5:
                        A5_R.Text = r.ToString();
                        break;

                    case SENSOR_ID.SENSOR_6:
                        A6_R.Text = r.ToString();
                        break;

                    case SENSOR_ID.SENSOR_7:
                        A7_R.Text = r.ToString();
                        break;

                }
            }, null);

        }
        private void Form1_Load(object sender, EventArgs e)
        {
            synchronizationContext = SynchronizationContext.Current;

        }
        //TODO:这里应该使用多线程
        private void HomeAxisButton_Click(object sender, EventArgs e)
        {
            try
            {
                synchronizationContext.Post(_ =>
                {
                    upButton.Enabled = false;
                    downButton.Enabled = false;
                    rightButton.Enabled = false;
                    leftButton.Enabled = false;

                }, null);

                motorControl.executeHome();
                synchronizationContext.Post(_ =>
                {
                    upButton.Enabled = true;
                    downButton.Enabled = true;
                    rightButton.Enabled = true;
                    leftButton.Enabled = true;
                }, null);



            }
            catch (Exception ex)
            {
                onViewDisplayError(ex);
            }
        }
        /// <summary>
        /// 利用对话框弹出错误信息
        /// </summary>
        /// <param name="ex"></param>
        public void onViewDisplayError(Exception ex)
        {
            synchronizationContext.Post(_ =>
            {

                DialogResult errormsgbox = DialogResult;
                MessageBox.Show("Error Message: " + ex.Message + "\n" + "Error Source: "
                                    + ex.Source, "CMO Error", MessageBoxButtons.RetryCancel);
                if (errormsgbox == DialogResult.Cancel)
                {
                    // it is possible that this method was called from a thread other than the 
                    // GUI thread - if this is the case we must use a delegate to close the application.
                    //Dim d As New CloseApp(AddressOf ThreadSafeClose)
                    CloseApp d = new CloseApp(ThreadSafeClose);
                    this.Invoke(d);
                }
            }, null);

        }
        /// <summary>
        /// 绘制传感器图像
        /// </summary>
        /// <param name="id">传感器ID</param>
        /// <param name="data">数据</param>
        public void onViewPlot(SENSOR_ID id, double data)
        {

            synchronizationContext.Post(_ =>
            {
                StringBuilder series = new StringBuilder("Series");

                series.Append(((int)id + 1).ToString());

                if (sensorChart.Series[series.ToString()].Points.Count > 500)
                {
                    sensorChart.Series[series.ToString()].Points.Clear();
                }

                sensorChart.Series[series.ToString()].Points.AddY(data);

            }, null);

        }
        /// <summary>
        /// 绘制传感器数据图像
        /// </summary>
        /// <param name="id">传感器ID</param>
        /// <param name="data">数据</param>
        /// <param name="maxCount">最大数据量,超过这个数后图像将被清除后重画</param>
        public void onViewPlot(SENSOR_ID id, double data,int maxCount)
        {

            synchronizationContext.Post(_ =>
            {
                StringBuilder series = new StringBuilder("Series");

                series.Append(((int)id + 1).ToString());

                if (sensorChart.Series[series.ToString()].Points.Count > maxCount)
                {
                    sensorChart.Series[series.ToString()].Points.Clear();
                }

                sensorChart.Series[series.ToString()].Points.AddY(data);

            }, null);

        }
        public void ThreadSafeClose()
        {
            //If the calling thread is different than the GUI thread, then use the
            //delegate to close the application, otherwise call close() directly
            if (this.InvokeRequired)
            {
                CloseApp d = new CloseApp(ThreadSafeClose);
                this.Invoke(d);
            }
            else
                Close();
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {

            }
            catch (Exception ex)
            {
                onViewDisplayError(ex);
            }
        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }


        private void leftButton_Click(object sender, EventArgs e)
        {
            //motorControl.motorControl(0, 1000);
        }


        private void upButton_Click(object sender, EventArgs e)
        {
            //motorControl.motorControl(1, 1000);

        }

        private void downButton_Click(object sender, EventArgs e)
        {
            //motorControl.motorControl(2, 1000);

        }

        private void rightButton_Click(object sender, EventArgs e)
        {
            Console.WriteLine("rightButton_Click");

            // motorControl.motorControl(3, 1000);

        }

        private void connectMotor_Click(object sender, EventArgs e)
        {
            if (motorControl.getMotorConnection() == MOTOR_CONNECTION.OK)
            {
                motorControl.disconnectMotor();

            }
            else
            {
                motorControl.motorInit();

            }
        }

        private void disconnectSocket_Click(object sender, EventArgs e)
        {

        }

        private void leftButtonKeyDown(object sender, KeyEventArgs e)
        {

        }

        private void leftButtonKeyUp(object sender, KeyEventArgs e)
        {

        }

        private void upButton_KeyDown(object sender, KeyEventArgs e)
        {

        }

        private void upButton_KeyPress(object sender, KeyPressEventArgs e)
        {

        }

        private void upButton_KeyUp(object sender, KeyEventArgs e)
        {

        }

        private void rightButton_KeyUp(object sender, KeyEventArgs e)
        {
            Console.WriteLine("rightButton_KeyUp");
        }

        private void rightButton_KeyDown(object sender, KeyEventArgs e)
        {
            Console.WriteLine("rightButton_KeyDown");

        }

        private void downButton_KeyDown(object sender, KeyEventArgs e)
        {

        }

        private void downButton_KeyUp(object sender, KeyEventArgs e)
        {

        }

        private void rightButton_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Console.WriteLine("rightButton_MouseUp");

            }



        }

        private void rightButton_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Console.WriteLine("rightButton_MouseDown");
                motorControl.motorControl(0, 1000);
            }



        }

        private void upButton_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                motorControl.motorControl(1, 1000);
            }

        }

        private void upButton_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {

            }

        }

        private void leftButton_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                motorControl.motorControl(2, 1000);

            }

        }

        private void leftButton_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {

            }

        }

        private void downButton_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                motorControl.motorControl(3, 1000);

            }

        }

        private void downButton_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {

            }
        }

        private void sendStringButton_Click(object sender, EventArgs e)
        {
            MySocket.Send(MySocket.getWorkingSocket(), this.sendStringTextbox.Text);

        }

        private void sendStringTextbox_TextChanged(object sender, EventArgs e)
        {
        }
        private void connectSensor_Click(object sender, EventArgs e)
        {
            if (Sensors.CreateInstance().getSensorConnection() != SENSOR_CONNECTION.OK)
            {
                if (this.COMportComboBox.SelectedItem != null)
                {
                    Console.WriteLine("准备连接" + COMportComboBox.SelectedItem.ToString());
                    Sensors.CreateInstance().connectSensor(COMportComboBox.SelectedItem.ToString());
                }
            }
            else if (Sensors.CreateInstance().getSensorConnection() == SENSOR_CONNECTION.OK)
            {
                Sensors.CreateInstance().disconnectSensor();
                this.connectSensor.Text = "连接传感器";
            }
        }

        private void COMportComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {

            Console.WriteLine("选择了" + COMportComboBox.SelectedItem.ToString());

        }

        private void chart1_Click(object sender, EventArgs e)
        {

        }

        private void groupBox4_Enter(object sender, EventArgs e)
        {

        }

        private void confirm_Click(object sender, EventArgs e)
        {
            //sensors.setSensorR(SENSOR_ID.SENSOR_1, double.Parse(this.A1_R.Text));
            //sensors.setSensorR(SENSOR_ID.SENSOR_2, double.Parse(this.A2_R.Text));
            //sensors.setSensorR(SENSOR_ID.SENSOR_3, double.Parse(this.A3_R.Text));
            //sensors.setSensorR(SENSOR_ID.SENSOR_4, double.Parse(this.A4_R.Text));
            //sensors.setSensorR(SENSOR_ID.SENSOR_5, double.Parse(this.A5_R.Text));
            //sensors.setSensorR(SENSOR_ID.SENSOR_6, double.Parse(this.A6_R.Text));
            //sensors.setSensorR(SENSOR_ID.SENSOR_7, double.Parse(this.A7_R.Text));
            sensors.setSensorQ(SENSOR_ID.SENSOR_1, double.Parse(this.A1_R.Text));
            sensors.setSensorQ(SENSOR_ID.SENSOR_2, double.Parse(this.A2_R.Text));
            sensors.setSensorQ(SENSOR_ID.SENSOR_3, double.Parse(this.A3_R.Text));
            sensors.setSensorQ(SENSOR_ID.SENSOR_4, double.Parse(this.A4_R.Text));
            sensors.setSensorQ(SENSOR_ID.SENSOR_5, double.Parse(this.A5_R.Text));
            sensors.setSensorQ(SENSOR_ID.SENSOR_6, double.Parse(this.A6_R.Text));
            sensors.setSensorQ(SENSOR_ID.SENSOR_7, double.Parse(this.A7_R.Text));



        }
    }
}